import React, { useState, useEffect, ReactText } from 'react';
import { Tree, Input, Select } from 'antd';

const { Search } = Input;

interface CascaderPlusProps {
	value?: string[];
	onChange?: (values: ReactText[]) => void;
	placeholder?: string;
	childrenKey?: string;
	keyName?: string;
	data: any[];
	isOnlyLeaf: boolean;
}

const getParentKey = (key: any, nodeList: any): any => {
	let parentKey;
	for (let i = 0; i < nodeList.length; i++) {
		const node = nodeList[i];
		if (node.children) {
			if (node.children.some((item: any) => item.key === key)) {
				parentKey = node.key;
			} else if (getParentKey(key, node.children)) {
				parentKey = getParentKey(key, node.children);
			}
		}
	}
	return parentKey;
};

export default function CascaderPlus(props: CascaderPlusProps): JSX.Element {
	// const [selectedKeys, setSelectedKeys] = useState<string[]>([]);
	const [searchValue, setSearchValue] = useState('');
	const [expandedKeys, setExpandedKeys] = useState<ReactText[]>([]);
	const [checkedKeys, setCheckedKeys] = useState<ReactText[]>([]);
	const [autoExpandParent, setAutoExpandParent] = useState<boolean>(true);
	const [selectValue, setSelectValue] = useState<ReactText[]>([]);
	const [data, setData] = useState<Array<any>>([]);
	const [dataList, setDataList] = useState<Array<any>>([]);
	const [selectOption, setSelectOption] = useState<Array<{ label: string; value: string }>>([]);

	useEffect(() => {
		setCheckedKeys(props.value || []);
		setSelectValue(props.value || []);
	}, [props.value]);

	useEffect(() => {
		setData(props.data);
		const list: any[] = [];
		const generateList = (data: any) => {
			for (let i = 0; i < data.length; i++) {
				const node = data[i];
				const { key, title } = node;
				list.push({ key, title });
				if (node.children) {
					generateList(node.children);
				}
			}
		};
		generateList(props.data);
		const option = list.map((item) => ({ label: item.title, value: item.key }));
		setSelectOption(option);
		setDataList(list);
	}, [props.data]);

	const tree2list = (treeData: any) => {
		const res = [];
		const queue = [];
		const childrenKey = props.childrenKey || 'children';
		queue.push(...treeData);
		while (queue.length) {
			const item: any = queue.shift();
			res.push(item);
			if (item[childrenKey] && Array.isArray(item[childrenKey]) && item[childrenKey].length) {
				queue.unshift(...item[childrenKey]);
			}
		}
		return res;
	};

	const list2Map = (nodeList: any[], key: string) => {
		const map = new Map();
		for (let i = 0; i < nodeList.length; i++) {
			const item = nodeList[i];
			map.set(item[key], item);
		}
		return map;
	};

	const pickLeaf = <T extends {}>(nodeList: T[]): T[] => {
		const key = props.keyName || 'key';
		const childrenKey = props.childrenKey || 'children';
		const treeList = tree2list(data);
		const treeMap = list2Map(treeList, key);
		return nodeList.filter((item) => !treeMap.get(item)[childrenKey]);
	};

	const onExpand = (expandedKeys: ReactText[]) => {
		setExpandedKeys(expandedKeys);
		setAutoExpandParent(false);
	};

	const onCheck = (checked: ReactText[] | { checked: ReactText[]; halfChecked: ReactText[] }): void => {
		const res = props.isOnlyLeaf ? pickLeaf<ReactText>(checked as ReactText[]) : (checked as ReactText[]);
		setCheckedKeys(res);
		setSelectValue(res);
		props.onChange && props.onChange(res);
	};

	const onChangeKeyWord = (e: React.ChangeEvent<HTMLInputElement>) => {
		const { value } = e.target;
		if (value) {
			const expandedKeys = dataList
				.map((item) => {
					if (item.title.indexOf(value) > -1) {
						return getParentKey(item.key, data);
					}
					return null;
				})
				.filter((item, i, self) => item && self.indexOf(item) === i);
			setExpandedKeys(expandedKeys);
			setSearchValue(value);
			setAutoExpandParent(true);
		} else {
			setExpandedKeys([]);
			setSearchValue(value);
			setAutoExpandParent(false);
		}
	};

	const handleChangeSelect = (values: string[]): void => {
		console.log(values);
		setSelectValue(values);
		setCheckedKeys(values);
		props.onChange && props.onChange(values);
	};

	const loop = (data: any) => {
		return data.map((item: any) => {
			const index = item.title.indexOf(searchValue);
			const beforeStr = item.title.substr(0, index);
			const afterStr = item.title.substr(index + searchValue.length);
			const title =
				index > -1 ? (
					<span>
						{beforeStr}
						<span className="c-blue">{searchValue}</span>
						{afterStr}
					</span>
				) : (
					<span>{item.title}</span>
				);
			if (item.children) {
				return { ...item, title, children: loop(item.children) };
			}

			return {
				...item,
				title,
				key: item.key,
			};
		});
	};

	return (
		<div>
			<div className="pb8 d-f">
				<div className="s0 pt4">已选择：</div>
				<Select
					mode="multiple"
					open={false}
					bordered={false}
					value={selectValue as []}
					style={{ width: '100%' }}
					options={selectOption}
					onChange={handleChangeSelect}
				/>
			</div>
			<Search style={{ marginBottom: 8 }} placeholder={props.placeholder || ''} onChange={onChangeKeyWord} />
			<Tree
				className="bg-w bor b-side-s p8"
				onExpand={onExpand}
				expandedKeys={expandedKeys}
				autoExpandParent={autoExpandParent}
				treeData={loop(data)}
				checkable
				onCheck={onCheck}
				checkedKeys={checkedKeys}
			/>
		</div>
	);
}
